/*
 * @Author: huangwei
 * @Date: 2021-05-14 17:13:42
 * @LastEditors: 黄威
 * @LastEditTime: 2022-02-15 17:10:40
 * @Description: 绘画用的mixin
 */
import type {
    GraphicLayer,
    GraphicType,
    DrawType,
    DrawOptions,
    Graphic,
} from 'types'
import type { PlottingBase } from './plugins/plotting'

import { Component } from 'vue-property-decorator'
import TipMixin from '@/mixins/tip-mixin'

import { AbsDraw } from '@/utils/draw/AbsDraw'
import newGraphic from '@/utils/bind-map/graphic'
import { measureDistance, meausreArea } from '@/utils/bind-map/measure'

@Component
export default class DrawMixin<
    T extends AbsDraw,
    V extends GraphicLayer
> extends TipMixin {
    drawIns!: T
    drawLayer!: V
    plottingPlugin?: PlottingBase

    /**
     * @public
     * 是否正在绘制
     * @returns {Boolean}
     */
    isDrawing(): boolean {
        return (
            !!this.drawIns._handler ||
            (this.plottingPlugin && this.plottingPlugin.mode === 'draw')
        )
    }

    /**
     * @public
     * 开始绘制
     * @param {DrawType} type 绘制类型
     * @param {DrawOptions} options 绘制参数
     * @param {String=} tip 展示的 tip 信息
     */
    startDraw(
        type: DrawType = 'Point',
        options: DrawOptions = {},
        tip?: string
    ) {
        // 取消军标事件
        if (this.plottingPlugin) this.plottingPlugin.setPlottingMode('select')

        // 联动绘制对象
        const linkDraws = (options.linkMaps || []).map(m => (m as any).drawIns)
        // 事件回调
        const events = options.events || {}

        this.drawIns.startDraw(type, {
            ...options,
            linkDraws,
            layer: options.layer || this.drawLayer,
            events: {
                ...events,
                drawend: (evt: any) => {
                    // 默认绘制完成事件
                    events.drawend && events.drawend(evt)

                    // 隐藏标签
                    this.hideTip()
                },
            },
        })

        // tip标签（draw事件都是异步执行，这里要等待上次绘制完成事件触发）
        setTimeout(() => {
            tip ? this.showTip(tip) : this.hideTip()
        }, 100)
    }

    /**
     * @public
     * 结束绘制（还原相关状态）
     */
    endDraw() {
        this.drawIns.endDraw(false)
    }

    /**
     * @public
     * 清空绘制图层
     */
    clearDraw() {
        this.drawLayer.clear()
    }

    /**
     * @public
     * 绘制多边形
     * @param {GraphicType} type 多边形类型
     * @param {[Number, Number, Number=] | [Number, Number, Number=][]} data 多边形顶点数组
     * @param style 样式
     * @param opt_options 其他参数
     * @param target 绘制到的对象图层 `GraphicLayer`
     * @returns {Graphic}
     */
    drawGraphic(
        type: GraphicType,
        data: any,
        style?: any,
        opt_options?: any,
        target?: any
    ): Graphic {
        return newGraphic(type, (this as any).MapType === '3D', opt_options)
            .setStyle(style)
            .setCoords(data)
            .addTo(target || this.drawLayer)
    }

    /**
     * @public
     * 量算
     * @param {'Polyline' | 'Polygon'} type 量算类型
     * @param opt_options 绘制参数
     */
    measure(type: 'Polyline' | 'Polygon', opt_options: any = {}) {
        const MeasureEvts = type === 'Polyline' ? measureDistance : meausreArea

        const events = MeasureEvts(
            (this as any).MapType === '3D',
            this.drawLayer,
            opt_options.markerStyle
        )

        this.startDraw(
            type,
            {
                repeatMode: true,
                linkMaps: opt_options.linkMaps,
                style: opt_options.style,
                events: {
                    ...events,
                    drawend: (evt: any) => {
                        opt_options.callback && opt_options.callback(evt.value)
                    },
                },
            },
            '左键点击添加点，右键结束测量！'
        )
    }
}
